#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include "esp_heap_caps.h"
#include "esp_system.h"
#include "esp_video_enc.h"
#include "esp_video_dec.h"
#include "video_codec_test_utils.h"
#include "esp_video_dec_reg.h"
#include "esp_video_enc_reg.h"
#include "esp_video_codec_utils.h"
#include "esp_video_enc_default.h"
#include "esp_video_dec_default.h"
#include "esp_video_codec_version.h"
#include "esp_log.h"
#include "video_codec_test.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "lvgl.h"
#include "esp_timer.h"
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include "esp_task_wdt.h"

#include "image_data.h"
#include "util.h"
#define TAG "VIDEO_CODEC_TEST"
#define FUNC_TIME_START(func_name) \
    int64_t start_time_##func_name = esp_timer_get_time(); \
    ESP_LOGI(TAG, "[%s] 开始执行", #func_name)

#define FUNC_TIME_END(func_name) \
    int64_t end_time_##func_name = esp_timer_get_time(); \
    int64_t duration_##func_name = end_time_##func_name - start_time_##func_name; \
    ESP_LOGI(TAG, "[%s] 执行完成，用时: %lld 微秒 (%.3f 毫秒)", \
             #func_name, duration_##func_name, duration_##func_name / 1000.0)

// 内部函数声明
void use_builtin_jpeg_data(test_codec_info_t *dec_info, esp_video_codec_resolution_t *resolution);

#define TEST_PATTERN_IS_VERTICAL (false)
#define TEST_PATTERN_BAR_COUNT   (8)

#define CODEC_TYPE_NAME(is_hw)   (is_hw ? "HW" : "SW")
#define MIN_RESOLUTION(a, b)     ((a.width * a.height > b.width * b.height) ? &b : &a)

#define TEST_DECLARE_QUERY_BY_DESC(query, desc) \
    esp_video_codec_query_t query = {           \
        .codec_type = (desc)->codec_type,       \
        .codec_cc = (desc)->codec_cc          \
    };

video_codec_test_res_t test_res1;
video_codec_test_res_t test_res2;

// 静态变量用于保持UI对象引用
static lv_obj_t *current_img_obj1 = NULL;
static lv_obj_t *current_img_obj2 = NULL;
static lv_obj_t *info_label_obj1 = NULL;
static lv_obj_t *info_label_obj2 = NULL;
static lv_obj_t *frame_counter_label1 = NULL;
static lv_obj_t *frame_counter_label2 = NULL;
static lv_image_dsc_t img_dsc1 = {0};
static lv_image_dsc_t img_dsc2 = {0};

lv_display_t *display1_ = NULL;
lv_display_t *display2_ = NULL;
lv_obj_t *screen1_ = NULL;
lv_obj_t *screen2_ = NULL;
void WriteMsgToDisplayTask(DisplayCmdMsgType type, uint16_t frame_idx, uint16_t frame_count);

// 视频模式优化：预分配固定的图像描述符，避免每帧重新设置源
static lv_image_dsc_t video_img_dsc1 = {0};
static lv_image_dsc_t video_img_dsc2 = {0};
static bool video_img_dsc_initialized1 = false;
static bool video_img_dsc_initialized2 = false;

// 性能优化用的缓存变量
static bool ui_initialized1 = false;
static bool ui_initialized2 = false;
static int last_frame_displayed1 = -1;
static int last_frame_displayed2 = -1;
static uint32_t last_width1 = 0, last_height1 = 0;
static uint32_t last_width2 = 0, last_height2 = 0;
static esp_video_codec_pixel_fmt_t last_pixel_format1 = 0; // 使用0作为无效值
static esp_video_codec_pixel_fmt_t last_pixel_format2 = 0; // 使用0作为无效值

int display_image_with_lvgl_ex1(bool is_video_mode, int current_frame, int total_frames);
// 使用LVGL显示解码后的图像（支持视频播放模式）
int display_image_with_lvgl(void)
{
    return display_image_with_lvgl_ex1(false, 0, 0);
}
// 详细的性能计时变量
int display_total_time_ms = 0;
int display_format_check_time_ms = 0;
int display_dsc_update_time_ms = 0;
int display_ui_init_time_ms = 0;
int display_clean_time_ms = 0;
int display_create_time_ms = 0;
int display_align_time_ms = 0;
int display_set_src_time_ms = 0;
int display_task_handler_time_ms = 0;

// 优化版本的LVGL图像显示函数，支持视频播放模式
bool need_set_src1 = false;
bool need_set_src2 = false;
int display_image_with_lvgl_ex1(bool is_video_mode, int current_frame, int total_frames)
{
    int64_t function_start_time = esp_timer_get_time();
    int64_t step_start_time, step_end_time;
    
    if (test_res1.decoded_data == NULL || test_res1.decoded_size == 0) {
        ESP_LOGE(TAG, "No decoded image data to display");
        return -1;
    }
    // 添加分辨率检查
    if (test_res1.res.width == 0 || test_res1.res.height == 0) {
        ESP_LOGE(TAG, "Invalid resolution: %lux%lu", test_res1.res.width, test_res1.res.height);
        return -1;
    }
    // 添加LVGL初始化检查
    if (!lv_is_initialized()) {
        ESP_LOGE(TAG, "LVGL not initialized");
        return -1;
    }

    // 确保screen1_有效
    if (!screen1_ || !lv_obj_is_valid(screen1_)) {
        ESP_LOGE(TAG, "screen1_ is not valid");
        return -1;
    }
    // 步骤1: 格式检查和缓存更新
    step_start_time = esp_timer_get_time();
    bool format_changed = (test_res1.res.width != last_width1 || 
                          test_res1.res.height != last_height1 ||
                          test_res1.dec_out_fmt != last_pixel_format1);
    
    // 仅在必要时确定LVGL颜色格式
    static lv_color_format_t lv_color_format = LV_COLOR_FORMAT_RGB565;
    static uint8_t bytes_per_pixel = 2;
    
    if (format_changed || !ui_initialized1) {
        switch (test_res1.dec_out_fmt) {
            case ESP_VIDEO_CODEC_PIXEL_FMT_RGB565_LE:
                lv_color_format = LV_COLOR_FORMAT_RGB565;
                bytes_per_pixel = 2;
                break;
            case ESP_VIDEO_CODEC_PIXEL_FMT_RGB888:
                lv_color_format = LV_COLOR_FORMAT_RGB888;
                bytes_per_pixel = 3;
                break;
            default:
                ESP_LOGE(TAG, "Unsupported pixel format for LVGL display: %s", 
                         esp_video_codec_get_pixel_fmt_str(test_res1.dec_out_fmt));
                return -1;
        }
        
        // 更新缓存
        last_width1 = test_res1.res.width;
        last_height1 = test_res1.res.height;
        last_pixel_format1 = test_res1.dec_out_fmt;
    }
    step_end_time = esp_timer_get_time();
    display_format_check_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤2: 图像描述符更新
    step_start_time = esp_timer_get_time();
    
    lv_image_dsc_t *active_img_dsc = &img_dsc1;  // 默认使用普通描述符
    
    if (is_video_mode) {
        // 视频模式：使用优化的描述符，减少每帧的开销
        if (!video_img_dsc_initialized1 || format_changed) {
            video_img_dsc1.header.magic = 0x19;  // LV_IMAGE_HEADER_MAGIC
            video_img_dsc1.header.cf = lv_color_format;
            video_img_dsc1.header.flags = 0;
            video_img_dsc1.header.w = test_res1.res.width;
            video_img_dsc1.header.h = test_res1.res.height;
            video_img_dsc1.header.stride = test_res1.res.width * bytes_per_pixel;
            video_img_dsc1.header.reserved_2 = 0;
            video_img_dsc1.data_size = test_res1.decoded_size;
            video_img_dsc_initialized1 = true;
        }
        
        // 每帧只更新数据指针（这是最快的操作）
        video_img_dsc1.data = test_res1.decoded_data;
        active_img_dsc = &video_img_dsc1;
        // if(current_frame > total_frames - 10 )
        // {
        //     //打印数据前20个数据
        //     for(int i = 0; i < 20; i++)
        //     {
        //         ESP_LOGI(TAG,"%d: %x",i,test_res1.decoded_data[i]);
        //     }

        // }
    } else {
        // 非视频模式：使用原有逻辑
        if (!ui_initialized1 || format_changed) {
            img_dsc1.header.magic = 0x19;  // LV_IMAGE_HEADER_MAGIC
            img_dsc1.header.cf = lv_color_format;
            img_dsc1.header.flags = 0;
            img_dsc1.header.w = test_res1.res.width;
            img_dsc1.header.h = test_res1.res.height;
            img_dsc1.header.stride = test_res1.res.width * bytes_per_pixel;
            img_dsc1.header.reserved_2 = 0;
            img_dsc1.data_size = test_res1.decoded_size;
        }
        
        // 每帧只更新数据指针
        img_dsc1.data = test_res1.decoded_data;
    }
    
    step_end_time = esp_timer_get_time();
    display_dsc_update_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤3: UI初始化（仅在必要时）
    step_start_time = esp_timer_get_time();
    bool need_ui_reinit = (!ui_initialized1 || (!is_video_mode || current_frame == 0) || format_changed);
    if (need_ui_reinit) {
        // 清理之前的显示内容
        if (ui_initialized1) {
            int64_t clean_start = esp_timer_get_time();
            lv_lock();
            if (current_img_obj1 && lv_obj_is_valid(current_img_obj1)) {
                lv_obj_del(current_img_obj1);  // <-- 改为删除对象而不是清屏
                current_img_obj1 = NULL;
            }
            lv_unlock();
            display_clean_time_ms = (esp_timer_get_time() - clean_start) / 1000;
        } else {
            display_clean_time_ms = 0;
        }
        current_img_obj1 = NULL;
        
        // 创建图像对象
        int64_t create_start = esp_timer_get_time();
        lv_lock();
        if (screen1_ && lv_obj_is_valid(screen1_)) {
            current_img_obj1 = lv_image_create(screen1_);
        }
        lv_unlock();
        display_create_time_ms = (esp_timer_get_time() - create_start) / 1000;
        
        if (current_img_obj1 == NULL) {
            ESP_LOGE(TAG, "Failed to create LVGL image object");
            return -1;
        }
        
        // 对齐图像
        int64_t align_start = esp_timer_get_time();
        lv_lock();
        if (lv_obj_is_valid(current_img_obj1)) {
            lv_obj_align(current_img_obj1, LV_ALIGN_CENTER, 0, 0);
        }
        lv_unlock();
        display_align_time_ms = (esp_timer_get_time() - align_start) / 1000;
        
        ui_initialized1 = true;
    } else {
        display_clean_time_ms = 0;
        display_create_time_ms = 0;
        display_align_time_ms = 0;
    }
    step_end_time = esp_timer_get_time();
    display_ui_init_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤4: 设置图像源（仅在必要时更新）
    step_start_time = esp_timer_get_time();
    if (current_img_obj1 != NULL && lv_obj_is_valid(current_img_obj1)) {
        lv_lock();
        if (is_video_mode) {
            // 视频模式优化：只在第一帧或格式改变时设置源
            need_set_src1 = (!ui_initialized1 || format_changed || current_frame == 0);
            
            if (need_set_src1) {

                lv_image_set_src(current_img_obj1, active_img_dsc);
            } else {
                // 其他帧只需要无效化对象来触发重绘，因为数据指针已经更新了

                lv_obj_invalidate(current_img_obj1);
                lv_refr_now(display1_);
            }
        } else {
            // 非视频模式：正常设置源
            lv_image_set_src(current_img_obj1, active_img_dsc);
        }
        lv_unlock();

    }
    // step_end_time = esp_timer_get_time();
    // display_set_src_time_ms = (step_end_time - step_start_time) / 1000;
    
    // // 步骤5: LVGL任务处理
    // step_start_time = esp_timer_get_time();
    // bool need_task_handler = (!ui_initialized1 || current_frame == 0 || format_changed || current_frame % 10 == 0);
    // if (need_task_handler) {
    //     // lv_lock();
    //     lv_task_handler();
    //     // lv_unlock();
    // }
    // step_end_time = esp_timer_get_time();
    display_task_handler_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 记录最后显示的帧
    last_frame_displayed1 = current_frame;
    
    // 计算总时间
    int64_t function_end_time = esp_timer_get_time();
    display_total_time_ms = (function_end_time - function_start_time) / 1000;
    
    // 如果总时间超过阈值，输出详细分析
    if (display_total_time_ms > 20) {  // 超过20ms就输出详细信息
        ESP_LOGW(TAG, "🐌 SLOW DISPLAY FRAME %d: total=%dms [format=%dms, dsc=%dms, ui_init=%dms(clean=%dms+create=%dms+align=%dms), set_src=%dms, need_set_src1:%s, task_handler=%dms]", 
                 current_frame, display_total_time_ms, display_format_check_time_ms, display_dsc_update_time_ms,
                 display_ui_init_time_ms, display_clean_time_ms, display_create_time_ms, display_align_time_ms,
                 display_set_src_time_ms, (need_set_src1 ? "true" : "false"), display_task_handler_time_ms);
    }
    
    return 0;
}

int display_image_with_lvgl_ex2(bool is_video_mode, int current_frame, int total_frames)
{
    int64_t function_start_time = esp_timer_get_time();
    int64_t step_start_time, step_end_time;
    
    if (test_res2.decoded_data == NULL || test_res2.decoded_size == 0) {
        ESP_LOGE(TAG, "No decoded image data to display");
        return -1;
    }
    // 添加分辨率检查
    if (test_res2.res.width == 0 || test_res2.res.height == 0) {
        ESP_LOGE(TAG, "Invalid resolution: %lux%lu", test_res2.res.width, test_res2.res.height);
        return -1;
    }
    // 添加LVGL初始化检查
    if (!lv_is_initialized()) {
        ESP_LOGE(TAG, "LVGL not initialized");
        return -1;
    }
    
    // 确保screen2_有效
    if (!screen2_ || !lv_obj_is_valid(screen2_)) {
        ESP_LOGE(TAG, "screen2_ is not valid");
        return -1;
    }
    
    // 步骤1: 格式检查和缓存更新
    step_start_time = esp_timer_get_time();
    bool format_changed = (test_res2.res.width != last_width2 || 
                          test_res2.res.height != last_height2 ||
                          test_res2.dec_out_fmt != last_pixel_format2);
    
    // 仅在必要时确定LVGL颜色格式
    static lv_color_format_t lv_color_format = LV_COLOR_FORMAT_RGB565;
    static uint8_t bytes_per_pixel = 2;
    
    if (format_changed || !ui_initialized2) {
        switch (test_res2.dec_out_fmt) {
            case ESP_VIDEO_CODEC_PIXEL_FMT_RGB565_LE:
                lv_color_format = LV_COLOR_FORMAT_RGB565;
                bytes_per_pixel = 2;
                break;
            case ESP_VIDEO_CODEC_PIXEL_FMT_RGB888:
                lv_color_format = LV_COLOR_FORMAT_RGB888;
                bytes_per_pixel = 3;
                break;
            default:
                ESP_LOGE(TAG, "Unsupported pixel format for LVGL display: %s", 
                         esp_video_codec_get_pixel_fmt_str(test_res2.dec_out_fmt));
                return -1;
        }
        
        // 更新缓存
        last_width2 = test_res2.res.width;
        last_height2 = test_res2.res.height;
        last_pixel_format2 = test_res2.dec_out_fmt;
    }
    step_end_time = esp_timer_get_time();
    display_format_check_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤2: 图像描述符更新
    step_start_time = esp_timer_get_time();
    
    lv_image_dsc_t *active_img_dsc = &img_dsc2;  // 默认使用普通描述符
    
    if (is_video_mode) {
        // 视频模式：使用优化的描述符，减少每帧的开销
        if (!video_img_dsc_initialized2 || format_changed) {
            video_img_dsc2.header.magic = 0x19;  // LV_IMAGE_HEADER_MAGIC
            video_img_dsc2.header.cf = lv_color_format;
            video_img_dsc2.header.flags = 0;
            video_img_dsc2.header.w = test_res2.res.width;
            video_img_dsc2.header.h = test_res2.res.height;
            video_img_dsc2.header.stride = test_res2.res.width * bytes_per_pixel;
            video_img_dsc2.header.reserved_2 = 0;
            video_img_dsc2.data_size = test_res2.decoded_size;
            video_img_dsc_initialized2 = true;
        }
        
        // 每帧只更新数据指针（这是最快的操作）
        video_img_dsc2.data = test_res2.decoded_data;
        active_img_dsc = &video_img_dsc2;
    } else {
        // 非视频模式：使用原有逻辑
        if (!ui_initialized2 || format_changed) {
            img_dsc2.header.magic = 0x19;  // LV_IMAGE_HEADER_MAGIC
            img_dsc2.header.cf = lv_color_format;
            img_dsc2.header.flags = 0;
            img_dsc2.header.w = test_res2.res.width;
            img_dsc2.header.h = test_res2.res.height;
            img_dsc2.header.stride = test_res2.res.width * bytes_per_pixel;
            img_dsc2.header.reserved_2 = 0;
            img_dsc2.data_size = test_res2.decoded_size;
        }
        
        // 每帧只更新数据指针
        img_dsc2.data = test_res2.decoded_data;
    }
    
    step_end_time = esp_timer_get_time();
    display_dsc_update_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤3: UI初始化（仅在必要时）
    step_start_time = esp_timer_get_time();
    bool need_ui_reinit = (!ui_initialized2 || (!is_video_mode || current_frame == 0) || format_changed);
    if (need_ui_reinit) {
        // 清理之前的显示内容
        if (ui_initialized2) {
            int64_t clean_start = esp_timer_get_time();
            lv_lock();
            if (current_img_obj2 && lv_obj_is_valid(current_img_obj2)) {
                lv_obj_del(current_img_obj2);  // <-- 改为删除对象而不是清屏
                current_img_obj2 = NULL;
            }
            lv_unlock();
            display_clean_time_ms = (esp_timer_get_time() - clean_start) / 1000;
        } else {
            display_clean_time_ms = 0;
        }
        current_img_obj2 = NULL;
        
        // 创建图像对象
        int64_t create_start = esp_timer_get_time();
        lv_lock();
        if (screen2_ && lv_obj_is_valid(screen2_)) {
            current_img_obj2 = lv_image_create(screen2_);
        }
        lv_unlock();
        display_create_time_ms = (esp_timer_get_time() - create_start) / 1000;
        
        if (current_img_obj2 == NULL) {
            ESP_LOGE(TAG, "Failed to create LVGL image object for screen2");
            return -1;
        }
        
        // 对齐图像
        int64_t align_start = esp_timer_get_time();
        lv_lock();
        if (lv_obj_is_valid(current_img_obj2)) {
            lv_obj_align(current_img_obj2, LV_ALIGN_CENTER, 0, 0);
        }
        lv_unlock();
        display_align_time_ms = (esp_timer_get_time() - align_start) / 1000;
        
        ui_initialized2 = true;
    } else {
        display_clean_time_ms = 0;
        display_create_time_ms = 0;
        display_align_time_ms = 0;
    }
    step_end_time = esp_timer_get_time();
    display_ui_init_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 步骤4: 设置图像源（仅在必要时更新）
    step_start_time = esp_timer_get_time();
    if (current_img_obj2 != NULL && lv_obj_is_valid(current_img_obj2)) {
        lv_lock();
        if (is_video_mode) {
            // 视频模式优化：只在第一帧或格式改变时设置源
            need_set_src2 = (!ui_initialized2 || format_changed || current_frame == 0);
            
            if (need_set_src2) {
                // ESP_LOGI(TAG, "set src for screen2");
                lv_image_set_src(current_img_obj2, active_img_dsc);
            } else {
                // 其他帧只需要无效化对象来触发重绘，因为数据指针已经更新了
                lv_obj_invalidate(current_img_obj2);
                lv_refr_now(display2_);
            }
        } else {
            // 非视频模式：正常设置源
            lv_image_set_src(current_img_obj2, active_img_dsc);
        }
        lv_unlock();
    }
    step_end_time = esp_timer_get_time();
    display_set_src_time_ms = (step_end_time - step_start_time) / 1000;
    
    // // 步骤5: LVGL任务处理
    // step_start_time = esp_timer_get_time();
    // bool need_task_handler = (!ui_initialized2 || current_frame == 0 || format_changed || current_frame % 10 == 0);
    // if (need_task_handler) {
    //     lv_task_handler();
    // }
    // step_end_time = esp_timer_get_time();
    // display_task_handler_time_ms = (step_end_time - step_start_time) / 1000;
    
    // 记录最后显示的帧
    last_frame_displayed2 = current_frame;
    
    // 计算总时间
    int64_t function_end_time = esp_timer_get_time();
    display_total_time_ms = (function_end_time - function_start_time) / 1000;
    
    // 如果总时间超过阈值，输出详细分析
    if (display_total_time_ms > 20) {  // 超过20ms就输出详细信息
        ESP_LOGW(TAG, "🐌 SLOW DISPLAY FRAME %d: total=%dms [format=%dms, dsc=%dms, ui_init=%dms(clean=%dms+create=%dms+align=%dms), set_src=%dms, need_set_src2:%s, task_handler=%dms]", 
                 current_frame, display_total_time_ms, display_format_check_time_ms, display_dsc_update_time_ms,
                 display_ui_init_time_ms, display_clean_time_ms, display_create_time_ms, display_align_time_ms,
                 display_set_src_time_ms, (need_set_src2 ? "true" : "false"), display_task_handler_time_ms);
    }
    
    return 0;
}


// 清理LVGL显示对象
void cleanup_lvgl_display(void)
{
    lv_lock();
    
    // 清理 screen1_ 的对象
    if (current_img_obj1 != NULL && ui_initialized1) {
        if (screen1_ && lv_obj_is_valid(screen1_)) {
            lv_obj_clean(screen1_);
        }
        current_img_obj1 = NULL;
        info_label_obj1 = NULL;
        frame_counter_label1 = NULL;
    }
    
    // 清理 screen2_ 的对象
    if (current_img_obj2 != NULL && ui_initialized2) {
        if (screen2_ && lv_obj_is_valid(screen2_)) {
            lv_obj_clean(screen2_);
        }
        current_img_obj2 = NULL;
        info_label_obj2 = NULL;
        frame_counter_label2 = NULL;
    }
    
    // 重置缓存变量
    ui_initialized1 = false;
    ui_initialized2 = false;
    last_frame_displayed1 = -1;
    last_frame_displayed2 = -1;
    last_width1 = 0;
    last_height1 = 0;
    last_width2 = 0;
    last_height2 = 0;
    last_pixel_format1 = 0;
    last_pixel_format2 = 0;
    video_img_dsc_initialized1 = false;
    video_img_dsc_initialized2 = false;
    
    lv_unlock();
}

// 释放预加载的帧缓冲区
void free_preloaded_frames(jpeg_frame_buffer_t *frame_buffers, int frame_count)
{
    if (frame_buffers == NULL) {
        return;
    }
    
    ESP_LOGI(TAG, "Freeing preloaded frame buffers...");
    
    for (int i = 0; i < frame_count; i++) {
        if (frame_buffers[i].data != NULL) {
            free(frame_buffers[i].data);
            frame_buffers[i].data = NULL;
        }
    }
    
    free(frame_buffers);
    ESP_LOGI(TAG, "Frame buffers freed");
}

// 使用预加载缓冲区播放多帧JPEG
int decode_preloaded_jpeg_frames1(test_codec_info_t *dec_info, jpeg_frame_buffer_t *frame_buffers, int frame_count)
{
    ESP_LOGI(TAG, "Starting preloaded JPEG frames decode and playback");
    
    // 打开解码器
    esp_video_dec_cfg_t dec_cfg = {
        .codec_type = dec_info->desc.codec_type,
        .codec_cc = dec_info->desc.codec_cc,
        .out_fmt = dec_info->fmt,
    };
    
    esp_video_dec_handle_t dec_handle = NULL;
    int ret = esp_video_dec_open(&dec_cfg, &dec_handle);
    if (ret != ESP_VC_ERR_OK || dec_handle == NULL) {
        ESP_LOGE(TAG, "Failed to open JPEG decoder, ret: %d", ret);
        return -1;
    }
    
    // 查询解码器能力
    esp_video_dec_caps_t dec_caps = { 0 };
    TEST_DECLARE_QUERY_BY_DESC(dec_query, &dec_info->desc);
    esp_video_dec_query_caps(&dec_query, &dec_caps);
    
    // 初始化解码输出缓冲区
    if (test_res1.decoded_data != NULL) {
        esp_video_codec_free(test_res1.decoded_data);
        test_res1.decoded_data = NULL;
    }
    
    // 播放参数 - 重新设计的稳定定时系统
    uint32_t frame_pts = 0;
    int precise_frame_interval_ms = 5000 / frame_count;  // 精确的帧间隔（毫秒）
    int64_t frame_interval_us = (int64_t)(precise_frame_interval_ms * 1000);  // 转换为微秒
    uint32_t delta_pts = (uint32_t)(precise_frame_interval_ms + 0.5f);  // PTS增量（毫秒）
    int decoded_frames = 0;
    
    ESP_LOGI(TAG, "🎬 Starting infinite loop playback...");
    ESP_LOGI(TAG, "📊 Animation: %d frames, 3 seconds, %.1f fps, %d ms per frame", 
             frame_count, (float)frame_count / 2.1, precise_frame_interval_ms);
    ESP_LOGI(TAG, "⏱️ Frame interval: %lld microseconds", frame_interval_us);
    
    int frame_idx = 0;
    int64_t playback_start_time = esp_timer_get_time();  // 播放开始的绝对时间基准
    int64_t cycle_start_time = playback_start_time;
    int64_t cycle_end_time = 0;
    bool first_cycle = true;
    int total_cycles = 0;
    int64_t absolute_frame_count = 0;  // 绝对帧计数器，不会重置
    
    // 播放控制：可以设置最大循环次数进行测试
    int max_test_cycles = -1;  // 设置为3个循环进行测试，设置为-1表示无限循环
    
    while (max_test_cycles < 0 || total_cycles < max_test_cycles) {
        // 计算当前帧的目标显示时间（基于播放开始时间的绝对时间）
        int64_t target_frame_time = playback_start_time + absolute_frame_count * frame_interval_us;
        int64_t frame_start_time = esp_timer_get_time();

        // 在帧处理循环中添加短暂延迟，给其他任务执行机会
        // if (frame_idx % 5 == 0) { // 每5帧添加一次延迟
        //     vTaskDelay(1); // 1个tick的延迟
        //     esp_task_wdt_reset(); // 同时喂狗
        // }
        // 获取当前帧数据
        jpeg_frame_buffer_t *frame_buf = &frame_buffers[frame_idx];
        
        // 跳过无效帧
        if (!frame_buf->valid || frame_buf->data == NULL || frame_buf->size == 0) {
            ESP_LOGW(TAG, "Skipping invalid frame %d", frame_idx);
            frame_pts += delta_pts;
            frame_idx = (frame_idx + 1) % frame_count;
            if (frame_idx < 0 || frame_idx >= frame_count) {
                frame_idx = 0;
            }
            continue;
}
                
        uint32_t aligned_size = (uint32_t)frame_buf->size;
        // ESP_LOGI(TAG, "decode main remain heap: %ld bytes", esp_get_free_heap_size());
        uint8_t *aligned_jpeg_data = esp_video_codec_align_alloc(dec_caps.in_frame_align, aligned_size, &aligned_size);
        if (aligned_jpeg_data == NULL) {
            
            ESP_LOGE(TAG, "Failed to allocate aligned input buffer for frame %d", frame_idx);
            ESP_LOGI(TAG, "decode main remain heap: %d bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));

            frame_pts += delta_pts;
            continue;
        }
        
        // 复制JPEG数据到对齐缓冲区
        memcpy(aligned_jpeg_data, frame_buf->data, frame_buf->size);
        // ESP_LOGI(TAG, "复制JPEG数据到对齐缓冲区 %ld bytes", esp_get_free_heap_size());
        // 准备解码输入帧
        esp_video_dec_in_frame_t dec_in_frame = {
            .data = aligned_jpeg_data,
            .size = frame_buf->size,
            .pts = frame_pts,
            .dts = frame_pts,
            .consumed = 0,
        };
        
        // 分配输出缓冲区（首次分配或根据需要重新分配）
        if (test_res1.decoded_data == NULL) {
            esp_video_codec_resolution_t default_res = {.width = 640, .height = 480};
            test_res1.decoded_size = esp_video_codec_get_image_size(dec_info->fmt, &default_res);
            test_res1.decoded_data = esp_video_codec_align_alloc(dec_caps.out_frame_align, 
                                                              test_res1.decoded_size, 
                                                              &test_res1.decoded_size);
        }
        
        esp_video_dec_out_frame_t dec_out_frame = {
            .data = test_res1.decoded_data,
            .size = test_res1.decoded_size,
        };
        
                // 执行解码
        int64_t decode_start_time = esp_timer_get_time();
        int64_t decode_process_time_us = 0;
        int decode_attempts = 0;
        
        while (dec_in_frame.consumed < dec_in_frame.size) {
            int64_t single_decode_start = esp_timer_get_time();
            ret = esp_video_dec_process(dec_handle, &dec_in_frame, &dec_out_frame);
            decode_process_time_us += (esp_timer_get_time() - single_decode_start);
            decode_attempts++;
            // ESP_LOGI(TAG, "esp_video_dec_process %d", ret);
            if (ret == ESP_VC_ERR_BUF_NOT_ENOUGH) {
                // 输出缓冲区不够，重新分配
                ESP_LOGI(TAG, "Output buffer too small, reallocating...");
                
                esp_video_codec_frame_info_t frame_info = {};
                ret = esp_video_dec_get_frame_info(dec_handle, &frame_info);
                if (ret != ESP_VC_ERR_OK) {
                    ESP_LOGE(TAG, "Failed to get frame info");
                    break;
                }
                
                // 释放旧缓冲区
                if (test_res1.decoded_data) {
                    esp_video_codec_free(test_res1.decoded_data);
                }
                
                // 重新分配
                test_res1.decoded_size = esp_video_codec_get_image_size(dec_info->fmt, &frame_info.res);
                test_res1.decoded_data = esp_video_codec_align_alloc(dec_caps.out_frame_align, 
                                                                  test_res1.decoded_size, 
                                                                  &test_res1.decoded_size);
                if (test_res1.decoded_data == NULL) {
                    ESP_LOGE(TAG, "Failed to reallocate output buffer");
                    ret = -1;
                    break;
                }
                
                dec_out_frame.data = test_res1.decoded_data;
                dec_out_frame.size = test_res1.decoded_size;
                
                // 重置并重试
                dec_in_frame.consumed = 0;
                continue;
                
            } else if (ret != ESP_VC_ERR_OK) {
                ESP_LOGE(TAG, "Frame %d decode failed, ret: %d", frame_idx, ret);
                break;
            }
            
            // 更新输入指针
            dec_in_frame.data += dec_in_frame.consumed;
            dec_in_frame.size -= dec_in_frame.consumed;
            dec_in_frame.consumed = 0;
        }   
        // 释放对齐的输入缓冲区
        esp_video_codec_free(aligned_jpeg_data);
        
        if (ret == ESP_VC_ERR_OK && dec_out_frame.decoded_size > 0) {
            // 获取帧信息
            esp_video_codec_frame_info_t frame_info = {};
            ret = esp_video_dec_get_frame_info(dec_handle, &frame_info);
            if (ret == ESP_VC_ERR_OK) {
                test_res1.res = frame_info.res;
                test_res1.dec_out_fmt = dec_info->fmt;
                decoded_frames++;
                // 添加数据有效性检查
                if (test_res1.res.width == 0 || test_res1.res.height == 0) {
                    ESP_LOGW(TAG, "Invalid frame dimensions: %lux%lu", test_res1.res.width, test_res1.res.height);
                    frame_pts += delta_pts;
                    frame_idx = (frame_idx + 1) % frame_count;
                    if (frame_idx < 0 || frame_idx >= frame_count) {
                        frame_idx = 0;
                    }
                    continue;
                }
                // 计算解码时间
                int64_t decode_end_time = esp_timer_get_time();
                int decode_total_time_ms = (decode_end_time - decode_start_time) / 1000;
                int decode_process_time_ms = decode_process_time_us / 1000;
                int decode_overhead_time_ms = decode_total_time_ms - decode_process_time_ms;
                
                // 如果解码时间异常，输出详细分析
                if (decode_total_time_ms > 50) {
                    ESP_LOGW(TAG, "🐌 SLOW DECODE FRAME %d: total=%dms, decode_process=%dms, overhead=%dms, attempts=%d", 
                             frame_idx, decode_total_time_ms, decode_process_time_ms, decode_overhead_time_ms, decode_attempts);
                }
                
                // 使用LVGL显示当前帧（视频模式）
                // display_image_with_lvgl_ex1(true, frame_idx, frame_count);                
                //发送显示消息

                WriteMsgToDisplayTask(Display1, frame_idx, frame_count);      

                // 精确的帧定时控制：基于绝对时间基准
                int64_t frame_end_time = esp_timer_get_time();
                
                // 计算处理时间统计
                int64_t total_processing_time_us = frame_end_time - frame_start_time;
                int total_processing_time_ms = total_processing_time_us / 1000;
                
                // 计算到下一帧目标时间的剩余时间
                int64_t next_frame_target_time = target_frame_time + frame_interval_us;
                int64_t time_until_next_frame = next_frame_target_time - frame_end_time;
                
                // 判断是否按时完成
                if (total_processing_time_us <= frame_interval_us) {
                    // 按时完成，计算需要延迟的时间
                    if (time_until_next_frame > 1000) {  // 至少1ms的延迟才有意义
                        int delay_ms = time_until_next_frame / 1000;
                        vTaskDelay(pdMS_TO_TICKS(delay_ms));
                        
                        // 可选：微秒级精确等待（如果需要更高精度）
                        int64_t remaining_us = time_until_next_frame % 1000;
                        if (remaining_us > 100) {  // 只对大于100微秒的时间进行忙等待
                            int64_t precise_target = frame_end_time + time_until_next_frame;
                            while (esp_timer_get_time() < precise_target) {
                                // 忙等待，提供微秒级精度
                                asm volatile("nop");
                            }
                        }
                        
                        ESP_LOGD(TAG, "Frame %d on schedule: processing=%dms, delay=%dms, target=%dms", 
                                 frame_idx, total_processing_time_ms, delay_ms, precise_frame_interval_ms);
                    } else {
                        // 刚好按时完成，无需延迟
                        ESP_LOGD(TAG, "Frame %d just on time: processing=%dms, target=%dms", 
                                 frame_idx, total_processing_time_ms, precise_frame_interval_ms);
                    }
                } else {
                    // 处理时间超过目标间隔，计算超时量
                    int64_t behind_schedule_us = total_processing_time_us - frame_interval_us;
                    int behind_schedule_ms = behind_schedule_us / 1000;
                    // 计算实际各部分时间总和用于验证
                    int calculated_total_ms = decode_total_time_ms + display_total_time_ms;
                    int time_difference_ms = total_processing_time_ms - calculated_total_ms;
                    
                    ESP_LOGW(TAG, "Frame %d behind schedule: total_measured=%dms (decode=%dms+display=%dms=%dms) diff=%dms, behind=%dms, target=%dms", 
                             frame_idx, total_processing_time_ms, decode_total_time_ms, display_total_time_ms, calculated_total_ms, time_difference_ms,
                             behind_schedule_ms, precise_frame_interval_ms);
                }
            }
        }
        
        // 更新时间戳和计数器
        frame_pts += delta_pts;
        absolute_frame_count++;  // 绝对帧计数器递增
        
        // 循环到下一帧
        // 修改为：
        frame_idx = (frame_idx + 1) % frame_count;
        if (frame_idx < 0 || frame_idx >= frame_count) {
            frame_idx = 0; // 确保索引有效
        }
        
        // 检测循环完成
        if (frame_idx == 0) {
            total_cycles++;
            cycle_end_time = esp_timer_get_time();
            
            if (first_cycle) {
                // 第一个循环完成，统计详细播放时间
                int64_t total_time_us = cycle_end_time - cycle_start_time;
                float total_time_s = total_time_us / 1000000.0;
                float total_time_ms = total_time_us / 1000.0;
                float actual_fps = frame_count / total_time_s;
                float target_fps = (float)frame_count / 3.0;
                
                ESP_LOGI(TAG, "⏱️ ===== FIRST CYCLE TIMING RESULTS =====");
                ESP_LOGI(TAG, "📊 Frames processed: %d", frame_count);
                ESP_LOGI(TAG, "⏰ Actual time: %.3f seconds (%.1f ms)", total_time_s, total_time_ms);
                ESP_LOGI(TAG, "🎯 Target time: 3.000 seconds");
                ESP_LOGI(TAG, "📈 Actual FPS: %.2f", actual_fps);
                ESP_LOGI(TAG, "🎯 Target FPS: %.2f", target_fps);
                ESP_LOGI(TAG, "⚡ Speed ratio: %.2f%% (%.3fx)", (3.0 / total_time_s) * 100, 3.0 / total_time_s);
                ESP_LOGI(TAG, "🎯 Timing accuracy: %.2f%% of target", (5.0 / total_time_s) * 100);
                ESP_LOGI(TAG, "=======================================");
                
                first_cycle = false;
            } else {
                // 后续循环的简化统计
                int64_t cycle_time_us = cycle_end_time - cycle_start_time;
                int64_t cycle_time_s = cycle_time_us / 1000000;
                int64_t cycle_fps = frame_count / cycle_time_s;
                
                ESP_LOGI(TAG, "🔄 Cycle %d completed: %llds, %lld fps", 
                         total_cycles, cycle_time_s, cycle_fps);
                // static uint16_t cnt = 0;
                // cnt++;
                // if(cnt == 3)
                // {
                //     char pcWriteBuffer[512] = {0};
                //     memset(pcWriteBuffer, 0, 512);
                //     vTaskList(pcWriteBuffer);
                //     printf("-----------------------------------\n");
                //     printf("name          state  priority  stack   num\n");
                //     printf("%s\n", pcWriteBuffer);
                //     char CPU_RunInfo[400] = {0}; // 保存任务运行时间信息
                //     memset(CPU_RunInfo, 0, 400); // 信息缓冲区清零
                //     vTaskGetRunTimeStats((char *)&CPU_RunInfo);
                //     printf("任务名       运行计数         使用率\r\n");
                //     printf("%s", CPU_RunInfo);
                //     printf("---------------------------------------------\r\n\n");
                //     //打印剩余ram和堆容量
                //     printf("IDLE: ****free internal ram %d  all heap size: %d Bytes****\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_8BIT));
                //     printf("IDLE: ****free SPIRAM size: %d Bytes****\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
                //     cnt = 0;
                // }
            }
            
            cycle_start_time = cycle_end_time;  // 为下个循环准备
            // 添加以下代码以确保显示刷新
            // lv_task_handler();
        }
    }
    
    // 播放完成，输出最终统计
    int64_t total_playback_time = esp_timer_get_time() - playback_start_time;
    int64_t total_playback_seconds = total_playback_time / 1000000;
    ESP_LOGI(TAG, "🎬 ===== PLAYBACK COMPLETED =====");
    ESP_LOGI(TAG, "📊 Total cycles: %d", total_cycles);
    ESP_LOGI(TAG, "⏰ Total playback time: %lld seconds", total_playback_seconds);
    if (total_cycles > 0) {
        ESP_LOGI(TAG, "📈 Average cycle time: %lld seconds", total_playback_seconds / total_cycles);
    }
    ESP_LOGI(TAG, "🎯 Target cycle time: 5.000 seconds");
    ESP_LOGI(TAG, "================================");
    
    // 关闭解码器
    esp_video_dec_close(dec_handle);
    
    // 清理解码输出缓冲区
    if (test_res1.decoded_data) {
        esp_video_codec_free(test_res1.decoded_data);
        test_res1.decoded_data = NULL;
    }
    ESP_LOGI(TAG, "🏁 Preloaded JPEG playback completed: %d/%d frames decoded", decoded_frames, frame_count);
    return 0;
}

int decode_preloaded_jpeg_frames2(test_codec_info_t *dec_info, jpeg_frame_buffer_t *frame_buffers, int frame_count)
{
    ESP_LOGI(TAG, "Starting preloaded JPEG frames decode and playback");
    
    // 打开解码器
    esp_video_dec_cfg_t dec_cfg = {
        .codec_type = dec_info->desc.codec_type,
        .codec_cc = dec_info->desc.codec_cc,
        .out_fmt = dec_info->fmt,
    };
    
    esp_video_dec_handle_t dec_handle = NULL;
    int ret = esp_video_dec_open(&dec_cfg, &dec_handle);
    if (ret != ESP_VC_ERR_OK || dec_handle == NULL) {
        ESP_LOGE(TAG, "Failed to open JPEG decoder, ret: %d", ret);
        return -1;
    }
    
    // 查询解码器能力
    esp_video_dec_caps_t dec_caps = { 0 };
    TEST_DECLARE_QUERY_BY_DESC(dec_query, &dec_info->desc);
    esp_video_dec_query_caps(&dec_query, &dec_caps);
    
    // 初始化解码输出缓冲区
    if (test_res2.decoded_data != NULL) {
        esp_video_codec_free(test_res2.decoded_data);
        test_res2.decoded_data = NULL;
    }
    
    // 播放参数 - 重新设计的稳定定时系统
    uint32_t frame_pts = 0;
    float precise_frame_interval_ms = 5000.0f / frame_count;  // 精确的帧间隔（毫秒）
    int64_t frame_interval_us = (int64_t)(precise_frame_interval_ms * 1000.0f);  // 转换为微秒
    uint32_t delta_pts = (uint32_t)(precise_frame_interval_ms + 0.5f);  // PTS增量（毫秒）
    int decoded_frames = 0;
    
    ESP_LOGI(TAG, "🎬 Starting infinite loop playback...");
    ESP_LOGI(TAG, "📊 Animation: %d frames, 3 seconds, %.1f fps, %.3f ms per frame", 
             frame_count, (float)frame_count / 3.0, precise_frame_interval_ms);
    ESP_LOGI(TAG, "⏱️ Frame interval: %lld microseconds", frame_interval_us);
    
    int frame_idx = 0;
    int64_t playback_start_time = esp_timer_get_time();  // 播放开始的绝对时间基准
    int64_t cycle_start_time = playback_start_time;
    int64_t cycle_end_time = 0;
    bool first_cycle = true;
    int total_cycles = 0;
    int64_t absolute_frame_count = 0;  // 绝对帧计数器，不会重置
    
    // 播放控制：可以设置最大循环次数进行测试
    int max_test_cycles = -1;  // 设置为3个循环进行测试，设置为-1表示无限循环
    
    while (max_test_cycles < 0 || total_cycles < max_test_cycles) {
        // 计算当前帧的目标显示时间（基于播放开始时间的绝对时间）
        int64_t target_frame_time = playback_start_time + absolute_frame_count * frame_interval_us;
        int64_t frame_start_time = esp_timer_get_time();

        // 在帧处理循环中添加短暂延迟，给其他任务执行机会
        // if (frame_idx % 5 == 0) { // 每5帧添加一次延迟
        //     vTaskDelay(1); // 1个tick的延迟
        //     esp_task_wdt_reset(); // 同时喂狗
        // }
        // 获取当前帧数据
        jpeg_frame_buffer_t *frame_buf = &frame_buffers[frame_idx];
        
        // 跳过无效帧
        if (!frame_buf->valid || frame_buf->data == NULL || frame_buf->size == 0) {
            ESP_LOGW(TAG, "Skipping invalid frame %d", frame_idx);
            frame_pts += delta_pts;
            frame_idx = (frame_idx + 1) % frame_count;
            if (frame_idx < 0 || frame_idx >= frame_count) {
                frame_idx = 0;
            }
            continue;
        }
                
        uint32_t aligned_size = (uint32_t)frame_buf->size;
        // ESP_LOGI(TAG, "decode main remain heap: %ld bytes", esp_get_free_heap_size());
        uint8_t *aligned_jpeg_data = esp_video_codec_align_alloc(dec_caps.in_frame_align, aligned_size, &aligned_size);
        if (aligned_jpeg_data == NULL) {
            
            ESP_LOGE(TAG, "Failed to allocate aligned input buffer for frame %d", frame_idx);
            ESP_LOGI(TAG, "decode main remain heap: %u bytes", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));

            frame_pts += delta_pts;
            continue;
        }
        
        // 复制JPEG数据到对齐缓冲区
        memcpy(aligned_jpeg_data, frame_buf->data, frame_buf->size);
        // ESP_LOGI(TAG, "复制JPEG数据到对齐缓冲区 %ld bytes", esp_get_free_heap_size());
        // 准备解码输入帧
        esp_video_dec_in_frame_t dec_in_frame = {
            .data = aligned_jpeg_data,
            .size = frame_buf->size,
            .pts = frame_pts,
            .dts = frame_pts,
            .consumed = 0,
        };
        
        // 分配输出缓冲区（首次分配或根据需要重新分配）
        if (test_res2.decoded_data == NULL) {
            esp_video_codec_resolution_t default_res = {.width = 640, .height = 480};
            test_res2.decoded_size = esp_video_codec_get_image_size(dec_info->fmt, &default_res);
            test_res2.decoded_data = esp_video_codec_align_alloc(dec_caps.out_frame_align, 
                                                              test_res2.decoded_size, 
                                                              &test_res2.decoded_size);
        }
        
        esp_video_dec_out_frame_t dec_out_frame = {
            .data = test_res2.decoded_data,
            .size = test_res2.decoded_size,
        };
        
                // 执行解码
        int64_t decode_start_time = esp_timer_get_time();
        int64_t decode_process_time_us = 0;
        int decode_attempts = 0;
        
        while (dec_in_frame.consumed < dec_in_frame.size) {
            int64_t single_decode_start = esp_timer_get_time();
            ret = esp_video_dec_process(dec_handle, &dec_in_frame, &dec_out_frame);
            decode_process_time_us += (esp_timer_get_time() - single_decode_start);
            decode_attempts++;
            
            if (ret == ESP_VC_ERR_BUF_NOT_ENOUGH) {
                // 输出缓冲区不够，重新分配
                ESP_LOGI(TAG, "Output buffer too small, reallocating...");
                
                esp_video_codec_frame_info_t frame_info = {};
                ret = esp_video_dec_get_frame_info(dec_handle, &frame_info);
                if (ret != ESP_VC_ERR_OK) {
                    ESP_LOGE(TAG, "Failed to get frame info");
                    break;
                }
                
                // 释放旧缓冲区
                if (test_res2.decoded_data) {
                    esp_video_codec_free(test_res2.decoded_data);
                }
                
                // 重新分配
                test_res2.decoded_size = esp_video_codec_get_image_size(dec_info->fmt, &frame_info.res);
                test_res2.decoded_data = esp_video_codec_align_alloc(dec_caps.out_frame_align, 
                                                                  test_res2.decoded_size, 
                                                                  &test_res2.decoded_size);
                if (test_res2.decoded_data == NULL) {
                    ESP_LOGE(TAG, "Failed to reallocate output buffer");
                    ret = -1;
                    break;
                }
                
                dec_out_frame.data = test_res2.decoded_data;
                dec_out_frame.size = test_res2.decoded_size;
                
                // 重置并重试
                dec_in_frame.consumed = 0;
                continue;
                
            } else if (ret != ESP_VC_ERR_OK) {
                ESP_LOGE(TAG, "Frame %d decode failed, ret: %d", frame_idx, ret);
                break;
            }
            
            // 更新输入指针
            dec_in_frame.data += dec_in_frame.consumed;
            dec_in_frame.size -= dec_in_frame.consumed;
            dec_in_frame.consumed = 0;
        }   
        // 释放对齐的输入缓冲区
        esp_video_codec_free(aligned_jpeg_data);
        
        if (ret == ESP_VC_ERR_OK && dec_out_frame.decoded_size > 0) {
            // 获取帧信息
            esp_video_codec_frame_info_t frame_info = {};
            ret = esp_video_dec_get_frame_info(dec_handle, &frame_info);
            if (ret == ESP_VC_ERR_OK) {
                test_res2.res = frame_info.res;
                test_res2.dec_out_fmt = dec_info->fmt;
                decoded_frames++;
            // 添加数据有效性检查
            if (test_res2.res.width == 0 || test_res2.res.height == 0) {
                ESP_LOGW(TAG, "Invalid frame dimensions: %lux%lu", test_res2.res.width, test_res2.res.height);
                frame_pts += delta_pts;
                frame_idx = (frame_idx + 1) % frame_count;
                if (frame_idx < 0 || frame_idx >= frame_count) {
                    frame_idx = 0;
                }
                continue;
            }
                // 计算解码时间
                int64_t decode_end_time = esp_timer_get_time();
                int decode_total_time_ms = (decode_end_time - decode_start_time) / 1000;
                int decode_process_time_ms = decode_process_time_us / 1000;
                int decode_overhead_time_ms = decode_total_time_ms - decode_process_time_ms;
                
                // 如果解码时间异常，输出详细分析
                if (decode_total_time_ms > 50) {
                    ESP_LOGW(TAG, "🐌 SLOW DECODE FRAME %d: total=%dms, decode_process=%dms, overhead=%dms, attempts=%d", 
                             frame_idx, decode_total_time_ms, decode_process_time_ms, decode_overhead_time_ms, decode_attempts);
                }
                
                // 使用LVGL显示当前帧（视频模式）
                // display_image_with_lvgl_ex2(true, frame_idx, frame_count);                
                //发送显示消息

                WriteMsgToDisplayTask(Display2, frame_idx, frame_count);         
                // 精确的帧定时控制：基于绝对时间基准
                int64_t frame_end_time = esp_timer_get_time();
                
                // 计算处理时间统计
                int64_t total_processing_time_us = frame_end_time - frame_start_time;
                int total_processing_time_ms = total_processing_time_us / 1000;
                
                // 计算到下一帧目标时间的剩余时间
                int64_t next_frame_target_time = target_frame_time + frame_interval_us;
                int64_t time_until_next_frame = next_frame_target_time - frame_end_time;
                
                // 判断是否按时完成
                if (total_processing_time_us <= frame_interval_us) {
                    // 按时完成，计算需要延迟的时间
                    if (time_until_next_frame > 1000) {  // 至少1ms的延迟才有意义
                        int delay_ms = time_until_next_frame / 1000;
                        vTaskDelay(pdMS_TO_TICKS(delay_ms));
                        
                        // 可选：微秒级精确等待（如果需要更高精度）
                        int64_t remaining_us = time_until_next_frame % 1000;
                        if (remaining_us > 100) {  // 只对大于100微秒的时间进行忙等待
                            int64_t precise_target = frame_end_time + time_until_next_frame;
                            while (esp_timer_get_time() < precise_target) {
                                // 忙等待，提供微秒级精度
                                asm volatile("nop");
                            }
                        }
                        
                        ESP_LOGD(TAG, "Frame %d on schedule: processing=%dms, delay=%dms, target=%.3fms", 
                                 frame_idx, total_processing_time_ms, delay_ms, precise_frame_interval_ms);
                    } else {
                        // 刚好按时完成，无需延迟
                        ESP_LOGD(TAG, "Frame %d just on time: processing=%dms, target=%.3fms", 
                                 frame_idx, total_processing_time_ms, precise_frame_interval_ms);
                    }
                } else {
                    // 处理时间超过目标间隔，计算超时量
                    int64_t behind_schedule_us = total_processing_time_us - frame_interval_us;
                    int behind_schedule_ms = behind_schedule_us / 1000;
                    // 计算实际各部分时间总和用于验证
                    int calculated_total_ms = decode_total_time_ms + display_total_time_ms;
                    int time_difference_ms = total_processing_time_ms - calculated_total_ms;
                    
                    ESP_LOGW(TAG, "Frame %d behind schedule: total_measured=%dms (decode=%dms+display=%dms=%dms) diff=%dms, behind=%dms, target=%.3fms", 
                             frame_idx, total_processing_time_ms, decode_total_time_ms, display_total_time_ms, calculated_total_ms, time_difference_ms,
                             behind_schedule_ms, precise_frame_interval_ms);
                }
            }
        }
        
        // 更新时间戳和计数器
        frame_pts += delta_pts;
        absolute_frame_count++;  // 绝对帧计数器递增
        
        // 循环到下一帧

        frame_idx = (frame_idx + 1) % frame_count;
        if (frame_idx < 0 || frame_idx >= frame_count) {
            frame_idx = 0; // 确保索引有效
        }
        
        // 检测循环完成
        if (frame_idx == 0) {
            total_cycles++;
            cycle_end_time = esp_timer_get_time();
            
            if (first_cycle) {
                // 第一个循环完成，统计详细播放时间
                int64_t total_time_us = cycle_end_time - cycle_start_time;
                float total_time_s = total_time_us / 1000000.0;
                float total_time_ms = total_time_us / 1000.0;
                float actual_fps = frame_count / total_time_s;
                float target_fps = (float)frame_count / 5.0;
                
                ESP_LOGI(TAG, "⏱️ ===== FIRST CYCLE TIMING RESULTS =====");
                ESP_LOGI(TAG, "📊 Frames processed: %d", frame_count);
                ESP_LOGI(TAG, "⏰ Actual time: %.3f seconds (%.1f ms)", total_time_s, total_time_ms);
                ESP_LOGI(TAG, "🎯 Target time: 5.000 seconds");
                ESP_LOGI(TAG, "📈 Actual FPS: %.2f", actual_fps);
                ESP_LOGI(TAG, "🎯 Target FPS: %.2f", target_fps);
                ESP_LOGI(TAG, "⚡ Speed ratio: %.2f%% (%.3fx)", (5.0 / total_time_s) * 100, 5.0 / total_time_s);
                ESP_LOGI(TAG, "🎯 Timing accuracy: %.2f%% of target", (5.0 / total_time_s) * 100);
                ESP_LOGI(TAG, "=======================================");
                
                first_cycle = false;
            } else {
                // 后续循环的简化统计
                int64_t cycle_time_us = cycle_end_time - cycle_start_time;
                float cycle_time_s = cycle_time_us / 1000000.0;
                float cycle_fps = frame_count / cycle_time_s;
                
                ESP_LOGI(TAG, "🔄 Cycle %d completed: %.3fs, %.1f fps", 
                         total_cycles, cycle_time_s, cycle_fps);
            }
            
            cycle_start_time = cycle_end_time;  // 为下个循环准备
            // 添加以下代码以确保显示刷新
            // lv_lock();
            // lv_task_handler();
            // lv_unlock();
        }
    }
    
    // 播放完成，输出最终统计
    int64_t total_playback_time = esp_timer_get_time() - playback_start_time;
    float total_playback_seconds = total_playback_time / 1000000.0;
    ESP_LOGI(TAG, "🎬 ===== PLAYBACK COMPLETED =====");
    ESP_LOGI(TAG, "📊 Total cycles: %d", total_cycles);
    ESP_LOGI(TAG, "⏰ Total playback time: %.3f seconds", total_playback_seconds);
    if (total_cycles > 0) {
        ESP_LOGI(TAG, "📈 Average cycle time: %.3f seconds", total_playback_seconds / total_cycles);
    }
    ESP_LOGI(TAG, "🎯 Target cycle time: 5.000 seconds");
    ESP_LOGI(TAG, "================================");
    
    // 关闭解码器
    esp_video_dec_close(dec_handle);
    
    // 清理解码输出缓冲区
    if (test_res2.decoded_data) {
        esp_video_codec_free(test_res2.decoded_data);
        test_res2.decoded_data = NULL;
    }
    
    ESP_LOGI(TAG, "🏁 Preloaded JPEG playback completed: %d/%d frames decoded", decoded_frames, frame_count);
    return 0;
}

// 比较函数，用于按文件名中的数字排序
static int compare_frame_files(const void *a, const void *b)
{
    const struct dirent *entry_a = (const struct dirent *)a;
    const struct dirent *entry_b = (const struct dirent *)b;
    
    // 提取文件名中的数字进行比较
    int num_a = 0, num_b = 0;
    
    // 查找文件名中的数字部分
    sscanf(entry_a->d_name, "%*[^0-9]%d", &num_a);
    sscanf(entry_b->d_name, "%*[^0-9]%d", &num_b);
    
    return num_a - num_b;
}
#include "esp_flash.h"
int preload_jpeg_frames_from_flash( uint8_t video_num, int frame_count, jpeg_frame_buffer_t **frame_buffers, int *loaded_count)
{ 
    ESP_LOGI(TAG, "Pre-loading %d JPEG frames ", frame_count);
    // ESP_LOGI(TAG, "剩余堆大小: %d", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
    // 分配帧缓冲区数组
    int64_t alloc_start_time = esp_timer_get_time();
    *frame_buffers = (jpeg_frame_buffer_t*)calloc(frame_count, sizeof(jpeg_frame_buffer_t));
    int64_t alloc_end_time = esp_timer_get_time();
    ESP_LOGI(TAG, "calloc frame buffers array time: %.3f ms", (alloc_end_time - alloc_start_time) / 1000.0);
    
    if (*frame_buffers == NULL) {
        ESP_LOGE(TAG, "Failed to allocate frame buffers array");
        return -1;
    }

    *loaded_count = 0;
    size_t total_loaded_size = 0;
    image_info_t* info_file = NULL;
    if(video_num == 1)//需要改todo
    {
        info_file = left_files;
    }
    else
    {
        info_file = left_files;
    }
    //统计已成功载入的数据大小
    for (int frame_idx = 1; frame_idx < frame_count + 1; frame_idx++) {
        // vTaskDelay(1);
        jpeg_frame_buffer_t *frame_buf = &(*frame_buffers)[frame_idx - 1];
        size_t file_size = info_file[frame_idx - 1].size;
        //打印文件名，文件大小
        // ESP_LOGI(TAG, "Loading file: %s, size: %d", info_file[frame_idx - 1].name, file_size);
        // 分配内存并读取文件
        int64_t malloc_start_time = esp_timer_get_time();
        frame_buf->data = (uint8_t*)heap_caps_malloc(file_size, MALLOC_CAP_SPIRAM);
        int64_t malloc_end_time = esp_timer_get_time();
        // ESP_LOGI(TAG, "heap_caps_malloc time: %.3f ms for %zu bytes", (malloc_end_time - malloc_start_time) / 1000.0, file_size);
        // ESP_LOGI(TAG, "剩余堆大小: %d", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
        if(frame_idx == 1 || frame_idx == 2)
        {
            ESP_LOGI(TAG, "First frame address: 0x%08x", info_file[frame_idx - 1].offset);

        }
        // ESP_LOGI(TAG, "已载入数据大小: %d", total_loaded_size);
        if (frame_buf->data == NULL) {
            ESP_LOGE(TAG, "Failed to allocate memory for frame %d (%zu bytes)", frame_idx, file_size);
            //打印剩余堆大小
            frame_buf->valid = false;
            continue;
        }
        //从flash中读取图片
        int64_t flash_read_start_time = esp_timer_get_time();
        esp_err_t err = esp_flash_read(esp_flash_default_chip, frame_buf->data, info_file[frame_idx - 1].offset, info_file[frame_idx - 1].size);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Failed to read image from flash: %s", esp_err_to_name(err));
            free(frame_buf->data);
            frame_buf->data = NULL;
            frame_buf->valid = false;
            continue;
        }
        
          // 验证 JPEG 文件头
    // if (frame_buf->data[0] == 0xFF && frame_buf->data[1] == 0xD8 && frame_buf->data[2] == 0xFF) {
    //     ESP_LOGI(TAG, "Verification successful: JPEG header found in UI partition");
    // } else {
    //     ESP_LOGW(TAG, "Verification failed: JPEG header not found in UI partition");
    //     ESP_LOGW(TAG, "Expected JPEG header: 0xFF 0xD8 0xFF");
    //     ESP_LOGW(TAG, "Actual data: 0x%02X 0x%02X 0x%02X", frame_buf->data[0], frame_buf->data[1], frame_buf->data[2]);
    // }
        int64_t flash_read_end_time = esp_timer_get_time();
        // ESP_LOGI(TAG, "flash_read time: %.3f ms for %zu bytes", (flash_read_end_time - flash_read_start_time) / 1000.0, file_size);
        // 设置帧信息
        frame_buf->size = file_size;
        frame_buf->valid = true;
        (*loaded_count)++;
        total_loaded_size += file_size;

        // ESP_LOGI(TAG, "✓ Frame %d loaded: %zu bytes", frame_idx, file_size);
    }

    ESP_LOGI(TAG, "Pre-loading completed: %d/%d frames loaded, total size: %.2f KB", 
             *loaded_count, frame_count, total_loaded_size / 1024.0);
    int64_t load_end_time = esp_timer_get_time();
    ESP_LOGI(TAG, "load all frame buffers array time: %.3f ms", (load_end_time - alloc_start_time) / 1000.0);

    return (*loaded_count > 0) ? 0 : -1;
}

// 预加载所有JPEG帧到内存缓冲区
int preload_jpeg_frames(const char* base_path, int frame_count, jpeg_frame_buffer_t **frame_buffers, int *loaded_count)
{
    ESP_LOGI(TAG, "Pre-loading %d JPEG frames from: %s", frame_count, base_path);

    // 分配帧缓冲区数组
    int64_t alloc_start_time = esp_timer_get_time();
    *frame_buffers = (jpeg_frame_buffer_t*)calloc(frame_count, sizeof(jpeg_frame_buffer_t));
    int64_t alloc_end_time = esp_timer_get_time();
    ESP_LOGI(TAG, "calloc frame buffers array time: %.3f ms", (alloc_end_time - alloc_start_time) / 1000.0);
    
    if (*frame_buffers == NULL) {
        ESP_LOGE(TAG, "Failed to allocate frame buffers array");
        return -1;
    }

    *loaded_count = 0;
    size_t total_loaded_size = 0;

    for (int frame_idx = 1; frame_idx < frame_count + 1; frame_idx++) {
        vTaskDelay(5);
        jpeg_frame_buffer_t *frame_buf = &(*frame_buffers)[frame_idx - 1];

        // 构造文件名 (格式: 1.jpg, 2.jpg, 3.jpg, ...)
        int64_t snprintf_start_time = esp_timer_get_time();
        snprintf(frame_buf->filename, sizeof(frame_buf->filename), "%s/%d.jpeg", base_path, frame_idx);
        int64_t snprintf_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "snprintf filename time: %.3f ms", (snprintf_end_time - snprintf_start_time) / 1000.0);

        ESP_LOGI(TAG, "Loading frame %d: %s", frame_idx, frame_buf->filename);

        int64_t fopen_start_time = esp_timer_get_time();
        FILE *file = fopen(frame_buf->filename, "rb");
        int64_t fopen_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "fopen time: %.3f ms", (fopen_end_time - fopen_start_time) / 1000.0);
        
        if (file == NULL) {
            ESP_LOGW(TAG, "Cannot open file: %s, skipping", frame_buf->filename);
            frame_buf->valid = false;
            continue;
        }

        // 获取文件大小
        int64_t fseek_start_time = esp_timer_get_time();
        fseek(file, 0, SEEK_END);
        size_t file_size = ftell(file);
        fseek(file, 0, SEEK_SET);
        int64_t fseek_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "fseek and ftell time: %.3f ms", (fseek_end_time - fseek_start_time) / 1000.0);

        if (file_size == 0) {
            ESP_LOGW(TAG, "Empty file: %s, skipping", frame_buf->filename);
            fclose(file);
            frame_buf->valid = false;
            continue;
        }

        // 分配内存并读取文件
        int64_t malloc_start_time = esp_timer_get_time();
        frame_buf->data = (uint8_t*)heap_caps_malloc(file_size, MALLOC_CAP_SPIRAM);
        int64_t malloc_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "heap_caps_malloc time: %.3f ms for %zu bytes", (malloc_end_time - malloc_start_time) / 1000.0, file_size);
        
        if (frame_buf->data == NULL) {
            ESP_LOGE(TAG, "Failed to allocate memory for frame %d (%zu bytes)", frame_idx, file_size);
            fclose(file);
            frame_buf->valid = false;
            continue;
        }

        // 读取文件内容
        int64_t fread_start_time = esp_timer_get_time();
        size_t bytes_read = fread(frame_buf->data, 1, file_size, file);
        int64_t fread_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "fread time: %.3f ms for %zu bytes", (fread_end_time - fread_start_time) / 1000.0, file_size);
        if(frame_idx == 1)
        {
            //打印第一张图片的前20个字节
            ESP_LOGI(TAG, "First frame data:");
            for (int i = 0; i < 20; i++) {
                ESP_LOGI(TAG, "0x%02x", frame_buf->data[i]);
            }
        }
        int64_t fclose_start_time = esp_timer_get_time();
        fclose(file);
        int64_t fclose_end_time = esp_timer_get_time();
        ESP_LOGI(TAG, "fclose time: %.3f ms", (fclose_end_time - fclose_start_time) / 1000.0);

        if (bytes_read != file_size) {
            ESP_LOGE(TAG, "Failed to read complete file: %s", frame_buf->filename);
            free(frame_buf->data);
            frame_buf->data = NULL;
            frame_buf->valid = false;
            continue;
        }

        // 设置帧信息
        frame_buf->size = file_size;
        frame_buf->valid = true;
        (*loaded_count)++;
        total_loaded_size += file_size;

        ESP_LOGI(TAG, "✓ Frame %d loaded: %zu bytes", frame_idx, file_size);
    }

    ESP_LOGI(TAG, "Pre-loading completed: %d/%d frames loaded, total size: %.2f KB", 
             *loaded_count, frame_count, total_loaded_size / 1024.0);


    return (*loaded_count > 0) ? 0 : -1;
}

const char* jpeg_base_path1 = "/spiffs/panda";
const char* jpeg_base_path2 = "/spiffs/ceber";
int frame_count1 = 200;  // 可以根据实际文件数量调整
int frame_count2 = 200;  // 可以根据实际文件数量调整
// 预加载所有帧
jpeg_frame_buffer_t *screen1_frame_buffers = NULL;
jpeg_frame_buffer_t *screen2_frame_buffers = NULL;
int loaded_count1 = 0;
int loaded_count2 = 0;
test_codec_info_t dec_info = {
    .desc.codec_type = ESP_VIDEO_CODEC_TYPE_MJPEG,
    .desc.is_hw = true,
    .desc.codec_cc = 0,
    .fmt = ESP_VIDEO_CODEC_PIXEL_FMT_RGB565_LE,
};
void preload_two_jpeg_freams(void)
{
    
    // FUNC_TIME_START(preload_jpeg_frames);
    // int ret = preload_jpeg_frames(jpeg_base_path1, frame_count1, &screen1_frame_buffers, &loaded_count1); 
    
    int ret = preload_jpeg_frames_from_flash(1, frame_count1, &screen1_frame_buffers, &loaded_count1); 
    //打印第一帧和第二帧的所有数据
    //打印第一帧的地址
    // ESP_LOGI(TAG, "First frame data: data size %u; address  ", screen1_frame_buffers[0].size);
    // for (int i = 0; i < screen1_frame_buffers[0].size; i++) {
    //     if (i % 64 == 0) {
    //         printf(" \r\n ");
    //     }
    //     printf( "%02x ", screen1_frame_buffers[0].data[i]);
    // }
    // printf("\n");
    // ESP_LOGI(TAG, "Second frame data:data size %u", screen1_frame_buffers[1].size);
    // for (int i = 0; i < screen1_frame_buffers[1].size; i++) {
    //     if (i % 64 == 0) {
    //         printf("\r\n ");
    //     }
    //     printf( "%02x ", screen1_frame_buffers[1].data[i]);
    // }
    // printf("\n");
    // ret = preload_jpeg_frames(jpeg_base_path2, frame_count2, &screen2_frame_buffers, &loaded_count2); 
    ret = preload_jpeg_frames_from_flash(0, frame_count2, &screen2_frame_buffers, &loaded_count2); 
    // FUNC_TIME_END(preload_jpeg_frames);

}
void test_preloaded_jpeg_playback1(void *arg)
{
    ESP_LOGI(TAG, "=== Starting Preloaded JPEG Playback Test ===");
    
    // 注册解码器
    esp_video_dec_register_default();

    if (loaded_count1 > 0) {
        ESP_LOGI(TAG, "💾 Pre-loading successful, starting playback...");
        
        // 播放预加载的帧
        // FUNC_TIME_START(decode_preloaded_jpeg_frames);
        int ret = decode_preloaded_jpeg_frames1(&dec_info, screen1_frame_buffers, frame_count1);
        // FUNC_TIME_END(decode_preloaded_jpeg_frames);
        
        if (ret == 0) {
            ESP_LOGI(TAG, "✅ Preloaded JPEG playback completed successfully");
        } else {
            ESP_LOGE(TAG, "❌ Preloaded JPEG playback failed");
        }
    } else {
        ESP_LOGE(TAG, "❌ Failed to preload JPEG frames");
    }
    
    // 清理预加载的缓冲区
    free_preloaded_frames(screen1_frame_buffers, frame_count1);
    
    // 注销解码器
    esp_video_dec_unregister_default();
    
    ESP_LOGI(TAG, "=== Preloaded JPEG Playback Test Completed ===");
}

void test_preloaded_jpeg_playback2(void *arg)
{
    ESP_LOGI(TAG, "=== Starting Preloaded JPEG Playback Test ===");
    
    // 注册解码器
    esp_video_dec_register_default();
    
    // 配置解码器
    test_codec_info_t dec_info = {
        .desc.codec_type = ESP_VIDEO_CODEC_TYPE_MJPEG,
        .desc.is_hw = true,
        .desc.codec_cc = 0,
        .fmt = ESP_VIDEO_CODEC_PIXEL_FMT_RGB565_LE,
    };

    if (loaded_count2 > 0) {
        ESP_LOGI(TAG, "💾 Pre-loading successful, starting playback...");
        
        // 播放预加载的帧
        // FUNC_TIME_START(decode_preloaded_jpeg_frames);
        int ret = decode_preloaded_jpeg_frames2(&dec_info, screen2_frame_buffers, frame_count2);
        // FUNC_TIME_END(decode_preloaded_jpeg_frames);
        
        if (ret == 0) {
            ESP_LOGI(TAG, "✅ Preloaded JPEG playback completed successfully");
        } else {
            ESP_LOGE(TAG, "❌ Preloaded JPEG playback failed");
        }
    } else {
        ESP_LOGE(TAG, "❌ Failed to preload JPEG frames");
    }
    
    // 清理预加载的缓冲区
    free_preloaded_frames(screen2_frame_buffers, frame_count2);
    
    // 注销解码器
    esp_video_dec_unregister_default();
    
    ESP_LOGI(TAG, "=== Preloaded JPEG Playback Test Completed ===");
}

void decode_task(void)
{
    preload_two_jpeg_freams();
    if(xTaskCreatePinnedToCore(test_preloaded_jpeg_playback1, "test_playback1", 1024 * 5, NULL, 5, NULL,0) == pdFAIL)
    {
        ESP_LOGI(TAG, "test_preloaded_jpeg_playback1 task creat fail");
        return ;
    }
    if(xTaskCreatePinnedToCore(test_preloaded_jpeg_playback2, "test_playback2", 1024 * 5, NULL, 5, NULL,0) == pdFAIL)
    {
        ESP_LOGI(TAG, "test_preloaded_jpeg_playback2 task creat fail");
        return ;
    }
}
#define DISPLAY_TASK_QUEUE_LENGTH 16
QueueHandle_t display_queue_handle_ = NULL;

void DisplayProcess(DisplayCmdMsgInfo msg_data)
{
    switch(msg_data.type)
    {
    case Display1:{
        if (test_res1.decoded_data != NULL && test_res1.decoded_size > 0) {
            // 添加有效性检查
            if (test_res1.res.width > 0 && test_res1.res.height > 0) {
                display_image_with_lvgl_ex1(true, msg_data.frame_idx, msg_data.frame_count);
            }
        }
        break;
    }
    case Display2:{
        if (test_res2.decoded_data != NULL && test_res2.decoded_size > 0) {
            // 添加有效性检查
            if (test_res2.res.width > 0 && test_res2.res.height > 0) {
                display_image_with_lvgl_ex2(true, msg_data.frame_idx, msg_data.frame_count);
            }
        }
        break;
    }
    default:
        break;
    }
    // 添加刷新调用
    // lv_lock();
    // lv_task_handler();
    // lv_unlock();
}
void DisplayTaskProcessHandler(void* arg){
    DisplayCmdMsgInfo msg_data;
    BaseType_t ret = pdFAIL;

    while (1)
    {
        memset(&msg_data, 0, sizeof(msg_data));
        ret = xQueueReceive(display_queue_handle_, &msg_data, portMAX_DELAY);
        if (ret != pdTRUE)
        {
            ESP_LOGE(TAG, "DisplayTaskProcessHandler TIMEOUT ERR : %d ! \r\n", ret);
            continue;
        }
        DisplayProcess(msg_data);

    }

}

//任务2：播放解码后的视频
void InitializeDisplayTask(){
    ESP_LOGI(TAG, "Init Display task");
    //消息队列初始化
    display_queue_handle_ = xQueueCreate(DISPLAY_TASK_QUEUE_LENGTH, sizeof(DisplayCmdMsgInfo));
    if(display_queue_handle_ == NULL)
    {
        ESP_LOGE(TAG, "sound_task_queue_ create failed");
        return;
    }
    //任务初始化
    if(xTaskCreatePinnedToCore(DisplayTaskProcessHandler, "DisplayTaskProcessHandler", 1024 * 4, NULL, 5, NULL, 1) == pdFAIL)
    {
        ESP_LOGI(TAG, "DisplayTaskProcessHandler task creat fail");
        return ;
    }
}



void WriteMsgToDisplayTask(DisplayCmdMsgType type, uint16_t frame_idx, uint16_t frame_count)
{
    // ESP_LOGI(TAG, "img queue size: %d",uxQueueMessagesWaiting(img_queue_handle_));    

    if(display_queue_handle_ == NULL)
    {
        ESP_LOGE(TAG, "display_queue_handle_ is null");
        return ;
    }
    // ESP_LOGI(TAG, "frame_idx: %hu frame_count: %hu, release queue: %hu", frame_idx, frame_count, uxQueueSpacesAvailable(display_queue_handle_));
    if (uxQueueSpacesAvailable(display_queue_handle_) == 0)
    {
        ESP_LOGE(TAG,"task img queue is full.");
        return ;
    }

    int ret = 0;
    DisplayCmdMsgInfo msg = {0};

    msg.type = type;
    msg.frame_idx = frame_idx;
    msg.frame_count = frame_count;
    ret = xQueueSend(display_queue_handle_, &msg, pdTICKS_TO_MS(0));
    if (ret != pdTRUE)
    {
        ESP_LOGE(TAG,"task display queue send failed.");
    }
    return ;
}